// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <pollux/functions/function_registry.h>

namespace kumo::pollux::fuzzer {

// Generates signatures of special forms for the expression fuzzer test to use.
class SpecialFormSignatureGenerator {
 public:
  virtual ~SpecialFormSignatureGenerator() {}

  /// Generates valid signatures for the specified special forms and append them
  /// to the signature map.
  /// @param specialForms Specifies a list of special form names delimited by
  /// comma.
  void appendSpecialForms(
      FunctionSignatureMap& signatureMap,
      const std::string& specialForms) const;

 protected:
  /// Generates signatures for cast from integral types to the given type and
  /// adds them to signatures.
  void addCastFromIntegralSignatures(
      const std::string& toType,
      std::vector<exec::FunctionSignaturePtr>& signatures) const;

  /// Generates signatures for cast from floating-point types to the given type
  /// and adds them to signatures.
  void addCastFromFloatingPointSignatures(
      const std::string& toType,
      std::vector<exec::FunctionSignaturePtr>& signatures) const;

  /// Generates signatures for cast from varchar to the given type and adds them
  /// to signatures.
  void addCastFromVarcharSignature(
      const std::string& toType,
      std::vector<exec::FunctionSignaturePtr>& signatures) const;

  /// Generates signatures for cast from timestamp to the given type and adds
  /// them to signatures.
  void addCastFromTimestampSignature(
      const std::string& toType,
      std::vector<exec::FunctionSignaturePtr>& signatures) const;

  /// Generates signatures for cast from date to the given type and adds them to
  /// signatures.
  void addCastFromDateSignature(
      const std::string& toType,
      std::vector<exec::FunctionSignaturePtr>& signatures) const;

  // Returns the map of special form names to their signatures.
  virtual const std::
      unordered_map<std::string, std::vector<exec::FunctionSignaturePtr>>&
      getSignatures() const;

  // Returns the signatures for the 'and' special form.
  virtual std::vector<exec::FunctionSignaturePtr> getSignaturesForAnd() const;

  // Returns the signatures for the 'or' special form.
  virtual std::vector<exec::FunctionSignaturePtr> getSignaturesForOr() const;

  // Returns the signatures for the 'coalesce' special form.
  virtual std::vector<exec::FunctionSignaturePtr> getSignaturesForCoalesce()
      const;

  // Returns the signatures for the 'if' special form.
  virtual std::vector<exec::FunctionSignaturePtr> getSignaturesForIf() const;

  // Returns the signatures for the 'switch' special form.
  virtual std::vector<exec::FunctionSignaturePtr> getSignaturesForSwitch()
      const;

  // Returns the signatures for the 'cast' special form.
  virtual std::vector<exec::FunctionSignaturePtr> getSignaturesForCast() const;

  // Creates a signature for the cast(fromType as toType).
  exec::FunctionSignaturePtr makeCastSignature(
      const std::string& fromType,
      const std::string& toType) const;

  const std::vector<std::string> kIntegralTypes_{
      "tinyint",
      "smallint",
      "integer",
      "bigint",
      "boolean"};

  const std::vector<std::string> kFloatingPointTypes_{"real", "double"};
};

} // namespace kumo::pollux::fuzzer
